/*
 * File Name  :Directs.java
 * Create Date:2012-11-6 上午12:22:55
 * Author     :woden
 */

package com.wodensoft.core.web;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JsonConfig;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wodensoft.util.json.JsonUtil;

/**
 * Action 框架下转发工具类，每一个action实例最终都需要依赖Directs中的静态方法来决定下一步。
 * 
 */
public final class Actions {
    /**
     * Logger for this class
     */
    private static final Logger logger = LoggerFactory.getLogger(Actions.class);

    /**
     * Action框架下的常量
     * 
     */
    public static class Constant {
        /**
         * 分页限制
         */
        public static Integer PAGE_LIMIT = 20;
    }

    /**
     * {@link HttpServletRequest#setAttribute(String, Object)}系统内部Keys.
     * 
     */
    public static enum Keys {
        /**
         * 当前路径（类+方法）
         */
        CUR_URL("_cur_url"),
        /**
         * 当前action路径
         */
        ACTION("_action"),
        /**
         * 当前工程的绝对根路径
         */
        CP("_cp"),
        /**
         * 当前页面所处的区域div id.
         */
        ZONE("_zone"),
        /**
         * 信息提示页:<br>
         * 信息提示类型详见{@link Styles}.
         */
        MSG_TYPE("_msg_type"),
        /**
         * 信息提示页:<br>
         * 信息内容.
         */
        MSG("_msg"),
        /**
         * 分页:<br>
         * 分页限制
         */
        LIMIT("_limit"),
        /**
         * 分页:<br>
         * 当前页数
         */
        PAGE("_page"),
        /**
         * 排序:<br>
         * 排序字段
         */
        FIELD("_field"),
        /**
         * 排序:<br>
         * 排序方向
         */
        DIR("_dir"),
        /**
         * 页面样式风格，默认值为"defalut"
         */
        STYLE("_style");

        private String name;

        private Keys(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    /**
     * web框架中使用的公共jsp页面路径.
     * 
     */
    public static enum Pages {
        /**
         * 信息提示页:<br>
         * 信息提示框架页.
         */
        MSG_PAGE("/common/msg.jsp"),

        /**
         * 分页标签内页
         */
        PAGE_BAR_TAG("/common/page_bar.jsp");

        private String page;

        private Pages(String page) {
            this.page = page;
        }

        public String getPage() {
            return page;
        }

    }

    /**
     * 界面CSS样式class
     * 
     */
    public static enum Styles {
        /**
         * 警告，黄色风格
         */
        MSG_WARNING("warning"),
        /**
         * 提示，蓝色风格
         */
        MSG_INFO("info"),
        /**
         * 错误，红色风格
         */
        MSG_ERROR("error");

        private String name;

        private Styles(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    /**
     * 辅助工具类
     * 
     */
    public static final class Util {

        /**
         * 获取根网址<br>
         * 返回例如:http://localhost:8080/aincs
         * 
         * @param request
         * @return
         */
        public static String getContextPath(HttpServletRequest request) {
            return request.getScheme() + "://" + request.getServerName()
                    + (request.getServerPort() == 80 ? "" : (":" + request.getServerPort())) + request.getContextPath();
        }

        /**
         * 得到真实的IP地址
         * 
         * @param request
         * @return
         */
        public static String getRealIpAddr(HttpServletRequest request) {
            String ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || StringUtils.equalsIgnoreCase("unknown", ip)) {
                ip = request.getRemoteAddr();
            }
            if (ip == null) {
                ip = "";
            }
            return ip;
        }

        /**
         * 将request的ParameterMap解析成字符串
         * 
         * @param request
         * @return
         */
        public static String builParameterString(HttpServletRequest request) {
            Map<String, String[]> map = request.getParameterMap();
            StringBuffer buffer = new StringBuffer();
            for (Object name : map.keySet()) {
                String[] values = map.get(name);
                if (values != null && values.length > 0) {
                    for (String value : values) {
                        buffer.append("&").append(name).append("=").append(value);
                    }
                }
            }

            if (buffer.equals("")) {
                buffer.append("&");
            }

            return buffer.substring(1);
        }

        /**
         * 获取当前action路径<br>
         * 如<b>/some/package/AnyAction</b>.
         * 
         * @param request
         * @return
         */
        public static String getActionUrl(HttpServletRequest request) {
            String strPathInfo = request.getServletPath();
            strPathInfo = strPathInfo.substring(0, strPathInfo.lastIndexOf("/"));
            return strPathInfo;
        }

        /**
         * 获取模块对应jsp页面路径<br>
         * 如<b>/some/package/AnyAction</b>.
         * 
         * @param request
         * @return
         */
        public static String getPagePath(HttpServletRequest request) {
            return "/module" + getActionUrl(request);
        }

        /**
         * 获取模块对应jsp页面路径<br>
         * 如<b>/some/package/AnyAction/demo.jsp</b>.
         * 
         * @param request
         * @param pageName
         *            jsp文件名
         * @return
         */
        public static String getPagePath(HttpServletRequest request, String pageName) {
            return getPagePath(request) + "/" + pageName;
        }

        /**
         * 获取排序方向
         * 
         * @param request
         * @return
         */
        public static String getSortDir(HttpServletRequest request) {
            String dir = request.getParameter(Keys.DIR.toString());
            if ("desc".equalsIgnoreCase(dir)) {
                dir = "desc";
            } else {
                dir = "asc";
            }
            return dir;
        }

        /**
         * 获取排序字段
         * 
         * @param request
         * @return
         */
        public static String getSortField(HttpServletRequest request) {
            String field = request.getParameter(Keys.FIELD.toString());
            return field;
        }

        /**
         * 获取分页限制
         * 
         * @param request
         * @return
         */
        public static Integer getLimit(HttpServletRequest request) {
            String strLimit = request.getParameter(Keys.LIMIT.toString());
            Integer limit;
            try {
                limit = Integer.parseInt(strLimit);
            } catch (Throwable e) {
                limit = Constant.PAGE_LIMIT;
            }
            return limit;
        }

        /**
         * 获取分页开始记录
         * 
         * @param request
         * @return
         */
        public static Integer getStart(HttpServletRequest request) {
            String strPage = request.getParameter(Keys.PAGE.toString());
            Integer page;
            try {
                page = Integer.parseInt(strPage);
            } catch (Throwable e) {
                page = 1;
            }
            Integer start = (page - 1) * getLimit(request);
            return start;
        }
    }

    /**
     * 文件下载
     * 
     * @param request
     * @param response
     * @param filename
     * @param is
     * @throws WebException
     */
    public static void download(HttpServletRequest request, HttpServletResponse response, String filename,
            InputStream is) throws WebException {
        try {
            OutputStream os = response.getOutputStream();
            response.reset(); // 清空输出流
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;  filename="
                    + new String(filename.getBytes("gb2312"), "ISO8859-1")); // 设定输出文件头

            byte[] b = new byte[1024];
            int len = -1;
            while ((len = is.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }

            is.close();
            os.flush();
            os.close();
            response.flushBuffer();
        } catch (IOException e) {
            throw new WebException("服务器找不到对应文件.", e);
        }
    }

    /**
     * 直接跳转<br>
     * 跳转到另一action<br>
     * 与redirectAction不同的是,使用这个方法跳转的时候,request信息不会丢失
     * 
     * @param request
     * @param response
     * @param actionUrl
     * @throws WebException
     */
    public static void forwardAction(HttpServletRequest request, HttpServletResponse response, String actionUrl)
            throws WebException {
        try {
            request.getRequestDispatcher(actionUrl).forward(request, response);
        } catch (Exception e) {
            logger.error("页面报错.", e);
            throw new WebException("系统内部处理出错.请联系系统管理员处理.", e);

        }
    }

    /**
     * action包含页面<br>
     * action处理业务完成之后，包含一个jsp页面时用此方法
     * 
     * @param request
     * @param response
     * @param msg
     * @throws WebException
     */
    public static void includePage(HttpServletRequest request, HttpServletResponse response, String pageURL)
            throws WebException {
        try {
            request.getRequestDispatcher(pageURL).forward(request, response);
        } catch (Exception e) {
            logger.error("页面报错.", e);
            throw new WebException("系统页面异常,请联系管理员处理.", e);
        }
    }

    /**
     * 直接跳转<br>
     * 跳转到另一action
     * 
     * @param request
     * @param response
     * @param url
     * @throws WebException
     */
    public static void redirectAction(HttpServletRequest request, HttpServletResponse response, String actionUrl)
            throws WebException {
        try {
            String contextPath = Actions.Util.getContextPath(request);
            // 补充公共参数
            if (request.getAttribute(Keys.ZONE.toString()) != null) {
                if (actionUrl.indexOf("?") > 0) {
                    actionUrl += ("&" + Keys.ZONE.toString() + "=" + request.getAttribute(Keys.ZONE.toString()));
                } else {
                    actionUrl += ("?" + Keys.ZONE.toString() + "=" + request.getAttribute(Keys.ZONE.toString()));
                }
            }

            response.sendRedirect(contextPath + actionUrl);
        } catch (Exception e) {
            logger.error("转向出错.", e);
            throw new WebException("系统内部处理出错.请联系系统管理员处理.", e);

        }
    }

    /**
     * 转向错误页面
     * 
     * @param request
     * @param response
     * @param msg
     * @throws WebException
     */
    public static void redirectErrorPage(HttpServletRequest request, HttpServletResponse response, String msg)
            throws WebException {
        redirectMsgPage(request, response, msg, Styles.MSG_ERROR);
    }

    /**
     * 转向信息提示页面
     * 
     * @param request
     * @param response
     * @param msg
     * @throws WebException
     */
    public static void redirectInfoPage(HttpServletRequest request, HttpServletResponse response, String msg)
            throws WebException {
        redirectMsgPage(request, response, msg, Styles.MSG_INFO);
    }

    /**
     * 转向到信息提示页面
     * 
     * @param request
     * @param response
     * @param title
     * @param msg
     * @param type
     * @throws WebException
     */
    public static void redirectMsgPage(HttpServletRequest request, HttpServletResponse response, String msg, Styles type)
            throws WebException {

        request.setAttribute(Keys.MSG.toString(), msg);
        request.setAttribute(Keys.MSG_TYPE.toString(), type.toString());
        try {
            request.getRequestDispatcher(Pages.MSG_PAGE.getPage()).forward(request, response);
        } catch (Exception e) {
            logger.error("转向出错", e);
            throw new WebException("转向出错.请联系系统管理员处理.", e);
        }
    }

    /**
     * 转向警告页面
     * 
     * @param request
     * @param response
     * @param msg
     * @throws WebException
     */
    public static void redirectWarningPage(HttpServletRequest request, HttpServletResponse response, String msg)
            throws WebException {
        redirectMsgPage(request, response, msg, Styles.MSG_WARNING);
    }

    /**
     * 以json方式展示
     * 
     * @param request
     * @param response
     * @param jsonObj
     * @throws WebException
     */
    public static void showJson(HttpServletRequest request, HttpServletResponse response, Object jsonObj)
            throws WebException {
        showJson(request, response, jsonObj, null);
    }

    /**
     * 以json方式展示
     * 
     * @param request
     * @param response
     * @param jsonObj
     * @param jsonConfig
     * @throws WebException
     */
    public static void showJson(HttpServletRequest request, HttpServletResponse response, Object jsonObj,
            JsonConfig jsonConfig) throws WebException {
        try {
            response.setContentType("application/json;charset=utf-8");
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();
            if (jsonConfig == null) {
                out.println(JsonUtil.tranBean2String(jsonObj));
            } else {
                out.println(JsonUtil.tranBean2String(jsonObj, jsonConfig));
            }
            out.flush();
            out.close();
        } catch (Exception e) {
            logger.error("转换JSON出错", e);
            throw new WebException("系统内部处理出错.请联系系统管理员处理.", e);
        }
    }
}